package com.design.patterns.structuralModel.chainofresponsibility;

import com.design.patterns.structuralModel.chainofresponsibility.bean.Request;
import com.design.patterns.structuralModel.chainofresponsibility.service.impl.AuthMiddleware;
import com.design.patterns.structuralModel.chainofresponsibility.service.impl.LimitingMiddleware;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * 责任链模式
 * 目的：使多个对象都有机会处理请求，从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链，并沿着这条链传递该请求，直到有一个对象处理它为止。
 * 就像中国有种古典玩具一样：连环锁，一环套一环，一直到最后一环结束
 *
 * 有两种实现此模式的方法：1.写一个接口  抽象业务处理方法和继续的规则，
 *                       2.写一个抽象类，将下一步的方法在抽象类中完成，再抽象出处理方法，其他实际业务类只需要调用就行了
 *                       3.声明接口后进行抽象类的转化，后续步骤与2相同
 * 我现在使用第三种方法实现责任链，模式
 */
public class ChainOfResponsibilityMain {
    /**
     * 首先我们创建传递的实体Request，这一步是很重要的：有些人觉得不需要传递实体，但是我觉得  将参数封装好，这样才符合软件设计的开闭原则
     * 接下来，我们创建接口Middleware，将传递的方法和内容抽象在里面，然后使用抽象MiddlewareAbstract进行抽象
     * 接下来，我们创建实际的业务逻辑，处理Request
     */
    /**
     * 我们模拟一个针对请求进行处理的方法:请求参数包含：请求头，请求体，Url
     * 责任链：
     * 1.请求限流AuthMiddleware
     * 2.请求头权限验证LimitingMiddleware
     *
     *
     * 责任链模式是一种把多个处理器组合在一起，依次处理请求的模式；
     * 责任链模式的好处是添加新的处理器或者重新排列处理器非常容易；
     * 责任链模式经常用在拦截、预处理请求等。
     */
    public static void main(String[] args) {
        /**
         * 请求1
         */
        Request request = new Request();
        request.setUrl("www.alaia.com");
        Map<String, Object> HeadMap = new HashMap<>();
        HeadMap.put("ip","127.0.0.1");
        request.setHead(HeadMap);
        Map<String, Object> QueryMap = new HashMap<>();
        QueryMap.put("Auth","admin");
        request.setQuery(QueryMap);
        /**
         * 请求2
         */
        Request request2 = new Request();
        request2.setUrl("www.alaia.com/c");
        Map<String, Object> HeadMap2 = new HashMap<>();
        HeadMap2.put("ip","127.0.0.1");
        request2.setHead(HeadMap2);
        Map<String, Object> QueryMap2 = new HashMap<>();
        QueryMap2.put("Auth","admin");
        request2.setQuery(QueryMap2);
        /**
         * 请求3
         */
        Request request3 = new Request();
        request3.setUrl("www.alaia.com/b");
        Map<String, Object> HeadMap3 = new HashMap<>();
        HeadMap3.put("ip","128.0.0.1");
        request3.setHead(HeadMap3);
        Map<String, Object> QueryMap3 = new HashMap<>();
        QueryMap3.put("Auth","user");
        request3.setQuery(QueryMap3);
        /**
         * 创建责任链
         * 注意责任处理对象的添加顺序，这关系到处理的顺序
         * JavaEE的Servlet规范定义的Filter就是一种责任链模式，它不但允许每个Filter都有机会处理请求，还允许每个Filter决定是否将请求“放行”给下一个Filter：
         * Servlet不但允许一个Filter自行决定处理ServletRequest和ServletResponse，还可以“伪造”ServletRequest和ServletResponse以便让下一个Filter处理，
         * 能实现非常复杂的功能。
         */
        LimitingMiddleware limitingMiddleware = new LimitingMiddleware();
        limitingMiddleware.linkWith(new AuthMiddleware())
                .linkWith(new AuthMiddleware());
        /**
         * 请求模拟
         */
        ArrayList<Request> requests = new ArrayList<>();
        requests.add(request);
        requests.add(request2);
        requests.add(request3);
        requests.forEach(
                (re) ->{
                    boolean check = limitingMiddleware.check(re);
                    if (check){
                        System.out.println("请求成功,链接：" + re.getUrl());
                    }else {
                        System.out.println("请求失败请查看原因");
                    }
                    System.out.println("=================================================");
                }
        );

    }

}
